package cn.iocoder.yudao.module.member.service.user;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
import cn.iocoder.yudao.framework.common.enums.TerminalEnum;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.module.member.controller.admin.user.vo.MemberUserPageReqVO;
import cn.iocoder.yudao.module.member.controller.admin.user.vo.MemberUserUpdateReqVO;
import cn.iocoder.yudao.module.member.controller.app.user.vo.AppMemberUserResetPasswordReqVO;
import cn.iocoder.yudao.module.member.controller.app.user.vo.AppMemberUserUpdateMobileReqVO;
import cn.iocoder.yudao.module.member.controller.app.user.vo.AppMemberUserUpdatePasswordReqVO;
import cn.iocoder.yudao.module.member.controller.app.user.vo.AppMemberUserUpdateReqVO;
import cn.iocoder.yudao.module.member.convert.auth.AuthConvert;
import cn.iocoder.yudao.module.member.convert.user.MemberUserConvert;
import cn.iocoder.yudao.module.member.dal.dataobject.user.MemberUserDO;
import cn.iocoder.yudao.module.member.dal.mysql.level.MemberLevelMapper;
import cn.iocoder.yudao.module.member.dal.mysql.user.MemberUserMapper;
import cn.iocoder.yudao.module.member.mq.producer.user.MemberUserProducer;
import cn.iocoder.yudao.module.pay.dal.dataobject.wallet.PayWalletDO;
import cn.iocoder.yudao.module.pay.dal.dataobject.wallet.PayWalletTransactionDO;
import cn.iocoder.yudao.module.pay.enums.wallet.PayWalletBizTypeEnum;
import cn.iocoder.yudao.module.pay.service.wallet.PayWalletService;
import cn.iocoder.yudao.module.system.api.sms.SmsCodeApi;
import cn.iocoder.yudao.module.system.api.sms.dto.code.SmsCodeUseReqDTO;
import cn.iocoder.yudao.module.system.enums.sms.SmsSceneEnum;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.google.common.annotations.VisibleForTesting;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.TransactionSynchronization;
import org.springframework.transaction.support.TransactionSynchronizationManager;

import javax.annotation.Resource;
import javax.validation.Valid;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.function.Predicate;

import static cn.iocoder.yudao.framework.common.enums.UserTypeEnum.MEMBER;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.framework.common.util.servlet.ServletUtils.getClientIP;
import static cn.iocoder.yudao.module.member.enums.ErrorCodeConstants.*;

/**
 * 会员 User Service 实现类
 *
 * @author 芋道源码
 */
@Service
@Valid
@Slf4j
public class MemberUserServiceImpl implements MemberUserService {

    @Resource
    private MemberUserMapper memberUserMapper;

    @Resource
    private SmsCodeApi smsCodeApi;

    @Resource
    private PasswordEncoder passwordEncoder;

    @Resource
    private MemberUserProducer memberUserProducer;

    @Resource
    private MemberLevelMapper memberLevelMapper;

    @Resource
    private PayWalletService payWalletService;

    private List<MemberUserDO> allMemberUserDOS = new ArrayList<>();

    @Override
    public MemberUserDO getUserByMobile(String mobile) {
        return memberUserMapper.selectByMobile(mobile);
    }

    @Override
    public List<MemberUserDO> getUserListByNickname(String nickname) {
        return memberUserMapper.selectListByNicknameLike(nickname);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public MemberUserDO createUserIfAbsent(String mobile, String registerIp, Integer terminal) {
        // 用户已经存在
        MemberUserDO user = memberUserMapper.selectByMobile(mobile);
        if (user != null) {
            return user;
        }
        // 用户不存在，则进行创建
        return createUser(mobile, registerIp, terminal);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public MemberUserDO createUserByPwd(String mobile, String password, String code) {
        // 用户已经存在
        MemberUserDO user = memberUserMapper.selectByMobile(mobile);
        if (user != null) {
            return user;
        }
        // 用户不存在，则进行创建
        return createUser(mobile, password, "127.0.0.1", TerminalEnum.APP.getTerminal(), code);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public MemberUserDO createUserByPwd(String mobile, String password, String code, String name) {
        // 用户已经存在
        MemberUserDO user = memberUserMapper.selectByMobile(mobile);
        if (user != null) {
            return user;
        }
        // 用户不存在，则进行创建
        return createUser(mobile, password, getClientIP(), TerminalEnum.APP.getTerminal(), code, name);
    }

    private MemberUserDO createUser(String mobile, String password, String registerIp, Integer terminal, String code, String name) {
        // 插入用户
        MemberUserDO user = new MemberUserDO();
        user.setMobile(mobile);
        user.setName(name);
        user.setNickname("暂无昵称");
        user.setStatus(CommonStatusEnum.ENABLE.getStatus()); // 默认开启
        user.setPassword(encodePassword(password)); // 加密密码
        user.setRegisterIp(registerIp);
        user.setRegisterTerminal(terminal);
        user.setCode(RandomUtil.randomString(8));
        user.setReferrer(code);
        user.setLevelId(new Long(0));
        user.setReferrerStatus(new Integer(0));

        user.setReferrerStatus(1);
        if (memberUserMapper.selectCount(new LambdaQueryWrapper<MemberUserDO>()
                .eq(MemberUserDO::getRegisterIp, registerIp)).equals(0)) {
            user.setReferrerStatus(0);
        }

        MemberUserDO referrerUser = this.memberUserMapper.selectOne(new LambdaQueryWrapper<MemberUserDO>()
                .eq(MemberUserDO::getCode, code));
        if (null != referrerUser) {
            user.setReferrerName(referrerUser.getNickname());
            user.setReferrerId(referrerUser.getId());

//            PayWalletDO payWalletDO = payWalletService.getOrCreateWallet(referrerUser.getId(), MEMBER.getValue());
//            payWalletService.addWalletBalance(payWalletDO.getId(), PayWalletBizTypeEnum.COMMISSION, );

            MemberUserPageReqVO memberUserPageReqVO = new MemberUserPageReqVO();
            memberUserPageReqVO.setCode(referrerUser.getCode());
            memberUserPageReqVO.setLevelId(referrerUser.getLevelId() - 1);
//            List<MemberUserDO> memberUserDOS = this.whetherCanBeUpgraded(memberUserPageReqVO);
//            if (memberUserDOS.size() >= 2) {
//                MemberUserDO memberUserDO = null;
//                memberUserDO = findLeafNodesWithCondition(referrerUser);
//                if (null != memberUserDO) {
//                    user.setReferrerId(memberUserDO.getId());
//                } else {
//                    user.setReferrerId(memberUserDOS.get(0).getId());
//                }
//            }
        }

        memberUserMapper.insert(user);

        // 发送 MQ 消息：用户创建
        TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() {

            @Override
            public void afterCommit() {
                memberUserProducer.sendUserCreateMessage(user.getId());
            }

        });
        return user;
    }

    private MemberUserDO createUser(String mobile, String password, String registerIp, Integer terminal, String code) {
        // 插入用户
        MemberUserDO user = new MemberUserDO();
        user.setMobile(mobile);
        user.setNickname("暂无昵称");
        user.setStatus(CommonStatusEnum.ENABLE.getStatus()); // 默认开启
        user.setPassword(encodePassword(password)); // 加密密码
        user.setRegisterIp(registerIp);
        user.setRegisterTerminal(terminal);
        user.setCode(RandomUtil.randomString(4));
        user.setReferrer(code);
        user.setLevelId(new Long(0));
        user.setReferrerStatus(new Integer(0));

        MemberUserDO referrerUser = this.memberUserMapper.selectOne(new LambdaQueryWrapper<MemberUserDO>()
                .eq(MemberUserDO::getCode, code));
        if (null != referrerUser) {
            user.setReferrerName(referrerUser.getNickname());
            user.setReferrerId(referrerUser.getId());

            MemberUserPageReqVO memberUserPageReqVO = new MemberUserPageReqVO();
            memberUserPageReqVO.setCode(referrerUser.getCode());
            memberUserPageReqVO.setLevelId(referrerUser.getLevelId() - 1);
            List<MemberUserDO> memberUserDOS = this.whetherCanBeUpgraded(memberUserPageReqVO);
            if (memberUserDOS.size() >= 2) {
                MemberUserDO memberUserDO = null;
                memberUserDO = findLeafNodesWithCondition(referrerUser);
                if (null != memberUserDO) {
                    user.setReferrerId(memberUserDO.getId());
                } else {
                    user.setReferrerId(memberUserDOS.get(0).getId());
                }
            }
        }

        memberUserMapper.insert(user);

        // 发送 MQ 消息：用户创建
        TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() {

            @Override
            public void afterCommit() {
                memberUserProducer.sendUserCreateMessage(user.getId());
            }

        });
        return user;
    }

    private MemberUserDO findLeafNodesWithCondition(MemberUserDO node) {
        MemberUserDO result;
        List<MemberUserDO> memberUserDOS = this.getAllNode(node.getId());
        if (memberUserDOS.size() == 0) {
            return null;
        }
        if (memberUserDOS.size() == 1) {
            result = memberUserDOS.get(0);
            return result;
        }

        result = findLeafNodesWithCondition(memberUserDOS.get(0));
        if (result != null) {
            return result;
        }
        result = findLeafNodesWithCondition(memberUserDOS.get(1));
        return result;
    }

    private List<MemberUserDO> getAllNode(Long code) {
        List<MemberUserDO> memberUserDOS = memberUserMapper.selectList(new LambdaQueryWrapper<MemberUserDO>()
                .eq(MemberUserDO::getReferrerId, code));
        return memberUserDOS;
    }

    private MemberUserDO createUser(String mobile, String registerIp, Integer terminal) {
        // 生成密码
        String password = IdUtil.fastSimpleUUID();
        // 插入用户
        MemberUserDO user = new MemberUserDO();
        user.setMobile(mobile);
        user.setStatus(CommonStatusEnum.ENABLE.getStatus()); // 默认开启
        user.setPassword(encodePassword(password)); // 加密密码
        user.setRegisterIp(registerIp);
        user.setRegisterTerminal(terminal);
        memberUserMapper.insert(user);

        // 发送 MQ 消息：用户创建
        TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() {

            @Override
            public void afterCommit() {
                memberUserProducer.sendUserCreateMessage(user.getId());
            }

        });
        return user;
    }

    @Override
    public void updateUserLogin(Long id, String loginIp) {
        memberUserMapper.updateById(new MemberUserDO().setId(id)
                .setLoginIp(loginIp).setLoginDate(LocalDateTime.now()));
    }

    @Override
    public MemberUserDO getUser(Long id) {
        return memberUserMapper.selectById(id);
    }

    @Override
    public MemberUserDO getUserByReferrer(String referrer) {
        return memberUserMapper.selectOne(new LambdaQueryWrapper<MemberUserDO>()
                .eq(MemberUserDO::getCode, referrer));
    }

    @Override
    public List<MemberUserDO> getUserList(Collection<Long> ids) {
        if (CollUtil.isEmpty(ids)) {
            return ListUtil.empty();
        }
        return memberUserMapper.selectBatchIds(ids);
    }

    @Override
    public void updateUser(Long userId, AppMemberUserUpdateReqVO reqVO) {
        memberUserMapper.updateById(new MemberUserDO().setId(userId)
                .setNickname(reqVO.getNickname())
                .setAvatar(reqVO.getAvatar())
                .setSex(reqVO.getSex()));
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateUserMobile(Long userId, AppMemberUserUpdateMobileReqVO reqVO) {
        // 检测用户是否存在
        MemberUserDO user = validateUserExists(userId);
        // 校验新手机是否已经被绑定
        validateMobileUnique(null, reqVO.getMobile());

        // 校验旧手机和旧验证码
        smsCodeApi.useSmsCode(new SmsCodeUseReqDTO().setMobile(user.getMobile()).setCode(reqVO.getOldCode())
                .setScene(SmsSceneEnum.MEMBER_UPDATE_MOBILE.getScene()).setUsedIp(getClientIP()));
        // 使用新验证码
        smsCodeApi.useSmsCode(new SmsCodeUseReqDTO().setMobile(reqVO.getMobile()).setCode(reqVO.getCode())
                .setScene(SmsSceneEnum.MEMBER_UPDATE_MOBILE.getScene()).setUsedIp(getClientIP()));

        // 更新用户手机
        memberUserMapper.updateById(MemberUserDO.builder().id(userId).mobile(reqVO.getMobile()).build());
    }

    @Override
    public void updateUserPassword(Long userId, AppMemberUserUpdatePasswordReqVO reqVO) {
        // 检测用户是否存在
        MemberUserDO user = validateUserExists(userId);
        // 校验验证码
//        smsCodeApi.useSmsCode(new SmsCodeUseReqDTO().setMobile(user.getMobile()).setCode(reqVO.getCode())
//                .setScene(SmsSceneEnum.MEMBER_UPDATE_PASSWORD.getScene()).setUsedIp(getClientIP()));

        // 更新用户密码
        memberUserMapper.updateById(MemberUserDO.builder().id(userId)
                .password(passwordEncoder.encode(reqVO.getNewPassword())).build());
    }

    @Override
    public void resetUserPassword(AppMemberUserResetPasswordReqVO reqVO) {
        // 检验用户是否存在
        MemberUserDO user = validateUserExists(reqVO.getMobile());

        // 使用验证码
        smsCodeApi.useSmsCode(AuthConvert.INSTANCE.convert(reqVO, SmsSceneEnum.MEMBER_RESET_PASSWORD,
                getClientIP()));

        // 更新密码
        memberUserMapper.updateById(MemberUserDO.builder().id(user.getId())
                .password(passwordEncoder.encode(reqVO.getPassword())).build());
    }

    private MemberUserDO validateUserExists(String mobile) {
        MemberUserDO user = memberUserMapper.selectByMobile(mobile);
        if (user == null) {
            throw exception(USER_MOBILE_NOT_EXISTS);
        }
        return user;
    }

    @Override
    public boolean isPasswordMatch(String rawPassword, String encodedPassword) {
        return passwordEncoder.matches(rawPassword, encodedPassword);
    }

    @Override
    public boolean checkPayPassword(Long id, String payPassword) {
        MemberUserDO memberUserDO = memberUserMapper.selectOne(new LambdaQueryWrapper<MemberUserDO>()
                .eq(MemberUserDO::getPayPassword, payPassword)
                .eq(MemberUserDO::getId, id));

        if (memberUserDO == null) {
            return false;
        }

        return true;
    }

    /**
     * 对密码进行加密
     *
     * @param password 密码
     * @return 加密后的密码
     */
    private String encodePassword(String password) {
        return passwordEncoder.encode(password);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateUser(MemberUserUpdateReqVO updateReqVO) {
        // 校验存在
        validateUserExists(updateReqVO.getId());
        // 校验手机唯一
        validateMobileUnique(updateReqVO.getId(), updateReqVO.getMobile());

        // 更新
        MemberUserDO updateObj = MemberUserConvert.INSTANCE.convert(updateReqVO);
        memberUserMapper.updateById(updateObj);
    }

    @VisibleForTesting
    MemberUserDO validateUserExists(Long id) {
        if (id == null) {
            return null;
        }
        MemberUserDO user = memberUserMapper.selectById(id);
        if (user == null) {
            throw exception(USER_NOT_EXISTS);
        }
        return user;
    }

    @VisibleForTesting
    void validateMobileUnique(Long id, String mobile) {
        if (StrUtil.isBlank(mobile)) {
            return;
        }
        MemberUserDO user = memberUserMapper.selectByMobile(mobile);
        if (user == null) {
            return;
        }
        // 如果 id 为空，说明不用比较是否为相同 id 的用户
        if (id == null) {
            throw exception(USER_MOBILE_USED, mobile);
        }
        if (!user.getId().equals(id)) {
            throw exception(USER_MOBILE_USED, mobile);
        }
    }

    @Override
    public PageResult<MemberUserDO> getUserPage(MemberUserPageReqVO pageReqVO) {
        return memberUserMapper.selectPage(pageReqVO);
    }

    @Override
    public void updateUserLevel(Long id, Long levelId, Long experience) {
        // 0 代表无等级：防止UpdateById时，会被过滤掉的问题
        levelId = ObjectUtil.defaultIfNull(levelId, 0L);
        memberUserMapper.updateById(new MemberUserDO()
                .setId(id)
                .setLevelId(levelId).setExperience(experience)
        );
    }

    @Override
    public Long getUserCountByGroupId(Long groupId) {
        return memberUserMapper.selectCountByGroupId(groupId);
    }

    @Override
    public Long getUserCountByLevelId(Long levelId) {
        return memberUserMapper.selectCountByLevelId(levelId);
    }

    @Override
    public Long getUserCountByTagId(Long tagId) {
        return memberUserMapper.selectCountByTagId(tagId);
    }

    @Override
    public boolean updateUserPoint(Long id, Integer point) {
        if (point > 0) {
            memberUserMapper.updatePointIncr(id, point);
        } else if (point < 0) {
            return memberUserMapper.updatePointDecr(id, point) > 0;
        }
        return true;
    }

    @Override
    public List<MemberUserDO> getReferrerByUserCode(String code) {

        List<MemberUserDO> memberUserDOS = memberUserMapper.selectList(new LambdaQueryWrapper<MemberUserDO>()
                .eq(MemberUserDO::getReferrer, code));
        memberUserDOS.stream().forEach(m -> {
            m.setMemberLevelDO(memberLevelMapper.selectById(m.getLevelId()));
        });

        return memberUserDOS;
    }

    @Override
    public List<MemberUserDO> getReferrerByUserId(Long userId) {

        List<MemberUserDO> memberUserDOS = memberUserMapper.selectList(new LambdaQueryWrapper<MemberUserDO>()
                .eq(MemberUserDO::getReferrerId, userId));
        memberUserDOS.stream().forEach(m -> {
            m.setMemberLevelDO(memberLevelMapper.selectById(m.getLevelId()));
        });

        return memberUserDOS;
    }

    @Override
    public List<MemberUserDO> getAllReferrerByUserId(Long userId) {
        allMemberUserDOS = new ArrayList<>();
        this.getAllReferrers(memberUserMapper.selectById(userId));
        allMemberUserDOS.stream().forEach(m -> {
            m.setMemberLevelDO(memberLevelMapper.selectById(m.getLevelId()));
        });
        return allMemberUserDOS;
    }

    @Override
    public void updatePayPassword(AppMemberUserUpdateReqVO reqVO) {
        memberUserMapper.updateById(MemberUserDO
                .builder()
                .id(reqVO.getId())
                .payPassword(reqVO.getPayPassword())
                .build());
    }

    private void getAllReferrers(MemberUserDO memberUserDO) {
        if (memberUserDO == null) {
            return;
        }

        allMemberUserDOS.add(memberUserDO);

        List<MemberUserDO> memberUserDOS = memberUserMapper.selectList(new LambdaQueryWrapper<MemberUserDO>()
                .eq(MemberUserDO::getReferrerId, memberUserDO.getId()));
        if (memberUserDOS.size() == 0) {
            return;
        }

        getAllReferrers(memberUserDOS.get(0));

        if (memberUserDOS.size() == 1) {
            return;
        }
        getAllReferrers(memberUserDOS.get(1));
    }

    @Override
    public List<MemberUserDO> whetherCanBeUpgraded(MemberUserPageReqVO memberUserPageReqVO) {
        LambdaQueryWrapper<MemberUserDO> wrapper = new LambdaQueryWrapper<>();

        if (null != memberUserPageReqVO.getCode() && StringUtils.isNotBlank(memberUserPageReqVO.getCode())) {
            wrapper.eq(MemberUserDO::getReferrer, memberUserPageReqVO.getCode());
        }
        if (null != memberUserPageReqVO.getLevelId()) {
            wrapper.eq(MemberUserDO::getLevelId, memberUserPageReqVO.getLevelId());
        }
        if (null != memberUserPageReqVO.getExperience()) {
            wrapper.ge(MemberUserDO::getExperience, memberUserPageReqVO.getExperience());
        }

        List<MemberUserDO> memberUserDOS = memberUserMapper.selectList(wrapper);
        return memberUserDOS;
    }

    @Override
    public Map<String, Object> betSum(String code, int level) {
        Map<String, Object> res = new HashMap<>();
        if (level == 1) {
            return memberUserMapper.selectMaps(new QueryWrapper<MemberUserDO>()
                            .select("IFNULL(count(id), 0) as sum_p")
                            .lambda()
                            .eq(MemberUserDO::getReferrer, code))
                    .get(0);
        }
        if (level == 2) {
            return memberUserMapper.selectMaps(new QueryWrapper<MemberUserDO>()
                            .select("IFNULL(count(id), 0) as sum_p")
                            .lambda()
                            .inSql(MemberUserDO::getReferrer, "select code from member_user where referrer = '" + code + "'"))
                    .get(0);
        }

        return res;
    }

    @Override
    public List<Map<String, Object>> allSum(String code) {
        String sql = " id, ";
        sql += " (SELECT IFNULL(sum(price), 0) AS sum_p FROM pay_wallet_transaction WHERE deleted = 0 AND (biz_type = 8 AND wallet_id IN (SELECT id FROM pay_wallet WHERE user_id = id AND tenant_id = 1)) AND tenant_id = 1) as sum_p, ";
        sql += " (SELECT IFNULL(sum(price), 0) AS sum_p FROM pay_wallet_transaction WHERE deleted = 0 AND (biz_type = 1 AND wallet_id IN (SELECT id FROM pay_wallet WHERE user_id = id AND tenant_id = 1)) AND tenant_id = 1) as sum_r, ";
        sql += " (SELECT IFNULL(sum(price), 0) AS sum_p FROM pay_wallet_transaction WHERE deleted = 0 AND (biz_type = 11 AND wallet_id IN (SELECT id FROM pay_wallet WHERE user_id = id AND tenant_id = 1)) AND tenant_id = 1) as sum_w ";

        return memberUserMapper.selectMaps(new QueryWrapper<MemberUserDO>()
                .select(sql)
                .lambda()
                .eq(MemberUserDO::getReferrer, code));
    }


    @Override
    public List<Map<String, Object>> rechargeSum(String code, LocalDate startTime, LocalDate endTime){

        DateTimeFormatter fmt = DateTimeFormatter.ofPattern("yyyy-MM-dd");

        String sql = " id,code,";
        // 最后充值时间
        sql += " (SELECT  IFNULL(Max(create_time),0) AS last_time FROM pay_wallet_transaction " +
                "WHERE deleted = 0 AND (biz_type = 1 AND " +
                "wallet_id IN (SELECT id FROM pay_wallet WHERE user_id = id AND tenant_id = 1)) AND tenant_id = 1) as last_time, ";
        // sql += "(SELECT IFNULL(total_recharge,0) FROM pay_wallet WHERE user_id = id AND tenant_id = 1) as  level_1_sum, ";
        // 本级累计充值
        sql += " (SELECT IFNULL(sum(price), 0) AS sum_p FROM pay_wallet_transaction " +
                "WHERE deleted = 0 " +
                " and create_time > '" + startTime.format(fmt) + "'" +
                " and create_time < '" + endTime.format(fmt) + "'" +
                "AND (biz_type = 1 AND wallet_id IN " +
                "(SELECT id FROM pay_wallet WHERE user_id = id AND tenant_id = 1)) AND tenant_id = 1) as level_1_sum ";
         return memberUserMapper.selectMaps(new QueryWrapper<MemberUserDO>()
                .select(sql)
                .lambda()
                .eq(MemberUserDO::getReferrer, code));
    }


}